package data

import (
	"061/Sgame/db"
	"061/Sgame/net"
	"061/Sgame/server/game/global"
	"061/Sgame/server/game/model"
	"061/Sgame/utils"
	"time"
)

const (
	ArmyCmdIdle        = 0 //空闲
	ArmyCmdAttack      = 1 //攻击
	ArmyCmdDefend      = 2 //驻守
	ArmyCmdReclamation = 3 //屯垦
	ArmyCmdBack        = 4 //撤退
	ArmyCmdConscript   = 5 //征兵
	ArmyCmdTransfer    = 6 //调动
)

const (
	ArmyStop    = 0
	ArmyRunning = 1
)

var ArmyDao = &armyDao{
	armyChan: make(chan *Army, 100),
}

type armyDao struct {
	armyChan chan *Army
}

//军队
type Army struct {
	Id                 int        `gorm:"column:id;primaryKey"`
	RId                int        `gorm:"column:rid"`
	CityId             int        `gorm:"column:cityId;comment:城市id"`
	Order              int8       `gorm:"column:order;comment:第几队 1-5队"`
	Generals           string     `gorm:"column:generals;comment:将领"`
	Soldiers           string     `gorm:"column:soldiers;comment:士兵"`
	ConscriptTimes     string     `gorm:"column:conscript_times;comment:征兵结束时间"` //征兵结束时间，json数组
	ConscriptCnts      string     `gorm:"column:conscript_cnts;comment:征兵数量"`    //征兵数量，json数组
	Cmd                int8       `gorm:"column:cmd;comment:命令  0:空闲 1:攻击 2：驻军 3:返回"`
	FromX              int        `gorm:"column:from_x;comment:来自x坐标"`
	FromY              int        `gorm:"column:from_y;comment:来自y坐标"`
	ToX                int        `gorm:"column:to_x;comment:去往x坐标"`
	ToY                int        `gorm:"column:to_y;comment:去往y坐标"`
	Start              time.Time  `json:"-" gorm:"column:start;comment:出发时间"`
	End                time.Time  `json:"-" gorm:"column:end;comment:到达时间"`
	State              int8       `gorm:"-"` //状态:0:running,1:stop
	GeneralArray       []int      `json:"-" gorm:"-"`
	SoldierArray       []int      `json:"-" gorm:"-"`
	ConscriptTimeArray []int64    `json:"-" gorm:"-"`
	ConscriptCntArray  []int      `json:"-" gorm:"-"`
	Gens               []*General `json:"-" gorm:"-"`
	CellX              int        `json:"-" gorm:"-"`
	CellY              int        `json:"-" gorm:"-"`
}

func (a *Army) TableName() string {
	return "army"
}

func (a *Army) ToModel() interface{} {
	p := model.Army{}
	p.CityId = a.CityId
	p.Id = a.Id
	p.UnionId = 0
	p.Order = a.Order
	p.Generals = a.GeneralArray
	p.Soldiers = a.SoldierArray
	p.ConTimes = a.ConscriptTimeArray
	p.ConCnts = a.ConscriptCntArray
	p.Cmd = a.Cmd
	p.State = a.State
	p.FromX = a.FromX
	p.FromY = a.FromY
	p.ToX = a.ToX
	p.ToY = a.ToY
	p.Start = a.Start.Unix()
	p.End = a.End.Unix()
	return p
}
func (a *Army) CheckConscript() {
	if a.Cmd == ArmyCmdConscript {
		finish := true
		for i, v := range a.ConscriptTimeArray {
			var cur = time.Now().Unix()
			if cur >= v {
				//征兵完成
				a.SoldierArray[i] = a.SoldierArray[i] + a.ConscriptCntArray[i]
				a.ConscriptTimeArray[i] = 0
				a.ConscriptCntArray[i] = 0
			} else {
				finish = false
			}
		}
		if finish {
			a.Cmd = ArmyCmdIdle
		}
	}
}

//pos 0-2
func (a *Army) PositionCanModify(pos int) bool {
	if pos >= 3 || pos < 0 {
		return false
	}
	if a.Cmd == ArmyCmdIdle {
		return true
	} else if a.Cmd == ArmyCmdConscript {
		endTime := a.ConscriptTimeArray[pos]
		return endTime == 0
	} else {
		return false
	}
}
func (a *Army) SyncExecute() {
	ArmyDao.armyChan <- a
	//通知客户端更新
	a.Push()
	a.CellX, a.CellY = a.Position()
}
func (a *Army) Position() (int, int) {
	diffTime := a.End.Unix() - a.Start.Unix()
	passTime := time.Now().Unix() - a.Start.Unix()
	rate := float32(passTime) / float32(diffTime)
	x := 0
	y := 0
	if a.Cmd == ArmyCmdBack {
		diffX := a.FromX - a.ToX
		diffY := a.FromY - a.ToY
		x = int(rate*float32(diffX)) + a.ToX
		y = int(rate*float32(diffY)) + a.ToY
	} else {
		diffX := a.ToX - a.FromX
		diffY := a.ToY - a.FromY
		x = int(rate*float32(diffX)) + a.FromX
		y = int(rate*float32(diffY)) + a.FromY
	}

	x = utils.MinInt(utils.MaxInt(x, 0), global.MapWith)
	y = utils.MinInt(utils.MaxInt(y, 0), global.MapHeight)
	return x, y
}
func (a *Army) Push() {
	net.Mgr.Push(a)
}
func (a *Army) IsCellView() bool {
	return true
}
func (a *Army) IsCanView(rid, x, y int) bool {
	return true
}
func (a *Army) BelongToRId() []int {
	return []int{a.RId}
}
func (a *Army) PushMsgName() string {
	return "army.push"
}
func (a *Army) TPosition() (int, int) {
	return a.ToX, a.ToY
}
func init() {
	go ArmyDao.running()
}
func (a *armyDao) running() {
	for {
		select {
		case army := <-a.armyChan:
			if army.Id > 0 {
				db.GormDB.Model(army).Where("id=?", army.Id).Select(
					"soldiers", "generals", "conscript_times",
					"conscript_cnts", "cmd", "from_x", "from_y", "to_x",
					"to_y", "start", "end").Updates(army)
			}
		}
	}

}

func init() {
	go ArmyDao.running()
}
